package com.mlog.njyjy.ndop.msg.admin.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.mlog.njyjy.ndop.msg.admin.service.FlowManagerService;
import com.mlog.njyjy.ndop.msg.common.domain.Flow;
import com.mlog.njyjy.ndop.msg.common.domain.NodeItem;
import com.mlog.njyjy.ndop.msg.persistence.dao.FlowRepository;
import com.mlog.njyjy.ndop.msg.persistence.dao.NodeItemRepository;
import com.mlog.njyjy.ndop.share.sql.support.SqlSort;
import com.mlog.njyjy.ndop.share.sql.support.SqlTableUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 消息流程管理service
 * </p>
 *
 * @author zyz
 * @version v1.0, 2020/8/11
 */
@Service
public class FlowManagerServiceImpl implements FlowManagerService {

    @Autowired
    private FlowRepository flowRepository;

    @Autowired
    private NodeItemRepository nodeItemRepository;

    /**
     * 列出所有流程
     *
     * @return
     */
    @Override
    public List<Flow> list() {

        return flowRepository.findAll(new SqlSort().setField("create_at").setOrder(SqlSort.Order.DESC));
    }

    /**
     * 创建或者更新一个流程
     *
     * @param flow
     * @return
     */
    @Override
    public Flow save(Flow flow) {

        Long id = flow.getId();
        boolean success;
        if (id == null) {
            //新增
            success = flowRepository.insert(flow);
        } else {
            //更新
            success = flowRepository.update(flow);
        }

        if (success) {
            return flowRepository.findFirst("select * from " + SqlTableUtil.getTblName(Flow.class)
                    + " where name = '" + flow.getName() + "'"
                    + " and type_name = '" + flow.getTypeName() + "'"
                    + " and times = '" + flow.getTimes() + "'");
        }
        return null;
    }

    /**
     * 导入流程配置文件
     *
     * @param sourceBytes
     * @return
     */
    @Override
    public List<Flow> importFlow(byte[] sourceBytes) {
        String string = new String(sourceBytes);
        JsonElement jsonElement = new JsonParser().parse(string);
        boolean isArr = jsonElement.isJsonArray();
        if (isArr) {
            JSONArray jsonArray = new JSONArray(string);
            List<Flow> flowList = JSONUtil.toList(jsonArray, Flow.class);
            flowList.forEach(this::addFlow);
        } else {
            Flow flow = JSONUtil.toBean(string, Flow.class);
            addFlow(flow);
        }
        return list();
    }


    /**
     * 添加流程
     *
     * @param flow
     */
    private void addFlow(Flow flow) {
        Flow flow1 = save(flow);
        if (flow1 != null && flow.getItems() != null) {
            saveNodes(flow1.getId(), flow.getItems());
        }
    }

    /**
     * 移除一个流程
     *
     * @param id
     * @return
     */
    @Override
    public boolean remove(Long id) {
        boolean success = flowRepository.delete(id);
        if (success) {
            removeByFlow(id);
        }
        return success;
    }

    /**
     * 新增或者修改流程节点
     *
     * @param nodeItems
     * @return
     */
    @Override
    public boolean saveNodes(Long flowId, List<NodeItem> nodeItems) {

        if (nodeItems != null && !nodeItems.isEmpty()) {
            nodeItems = nodeItems.stream().peek(nodeItem -> nodeItem.setFlowId(flowId)).collect(Collectors.toList());
            return nodeItemRepository.insert(nodeItems);
        }
        return false;

    }

    /**
     * 查找流程中的所有节点
     *
     * @param flowId
     * @return
     */
    @Override
    public List<NodeItem> findByFlow(Long flowId) {
        return nodeItemRepository.find("select * from " + SqlTableUtil.getTblName(NodeItem.class) + " where flow_id=?", flowId);
    }

    /**
     * 移除流程中的所有节点
     *
     * @param flowId
     * @return
     */
    @Override
    public boolean removeByFlow(Long flowId) {
        List<NodeItem> items = findByFlow(flowId);
        if (items != null) {
            items.forEach(nodeItem -> nodeItemRepository.delete(nodeItem.getId()));
        }

        List<NodeItem> itemList = findByFlow(flowId);
        return itemList == null;
    }

    /**
     * 移除流程中的单个节点
     *
     * @param id
     * @return
     */
    @Override
    public boolean removeNode(Long id) {
        NodeItem nodeItem = nodeItemRepository.findOne(id);
        boolean success = nodeItemRepository.delete(id);
        if (success) {
            List<NodeItem> nodeItemList = nodeItemRepository.find("select * from " + SqlTableUtil.getTblName(NodeItem.class)
                    + " where flow_id=? and sequence > ?", nodeItem.getFlowId(), nodeItem.getSequence());
            if (nodeItemList != null) {
                //次序往前调 更新
                nodeItemList.forEach(nodeItem1 -> {
                    nodeItem1.setSequence(nodeItem1.getSequence() - 1);
                    nodeItemRepository.update(nodeItem1);
                });

            }
        }
        return success;
    }


    /**
     * 添加单个节点 （备用 应该没啥用）
     *
     * @param nodeItem
     * @return
     */
    @Override
    public boolean addNode(NodeItem nodeItem) {
        List<NodeItem> nodeItemList = nodeItemRepository.find("select * from " + SqlTableUtil.getTblName(NodeItem.class)
                + " where flow_id=? and sequence > ?", nodeItem.getFlowId(), nodeItem.getSequence() - 1);
        if (nodeItemList != null) {
            //次序往后调 更新
            nodeItemList.forEach(nodeItem1 -> {
                nodeItem1.setSequence(nodeItem1.getSequence() + 1);
                nodeItemRepository.update(nodeItem1);
            });
        }
        //新增节点
        return nodeItemRepository.insert(nodeItem);
    }
}
